package socket

import (
	"sync"
)

// 会话访问
type SessionAccessor interface {

	// 获取一个连接
	GetSession(int) *SocketSession

	// 遍历连接
	VisitSession(func(*SocketSession) bool)

	// 连接数量
	SessionCount() int

	// 关闭所有连接
	CloseAllSession()

	GetSessionChangeCount() (int, int)

	ResetSessionChangeCount()
}

// 完整功能的会话管理
type SessionManager interface {
	SessionAccessor

	Add(*SocketSession, int)
	Remove(int)
	SetSession(int, *SocketSession)
}

type SessionManagerImplement struct {
	sesMap          map[int]*SocketSession
	newSessionCount int
	delSessionCount int
	sesMapGuard     sync.RWMutex
}

func (self *SessionManagerImplement) Add(ses *SocketSession, id int) {

	self.sesMapGuard.Lock()
	defer self.sesMapGuard.Unlock()

	self.sesMap[id] = ses
	self.newSessionCount++
}

func (self *SessionManagerImplement) Remove(id int) {
	self.sesMapGuard.Lock()
	defer self.sesMapGuard.Unlock()
	delete(self.sesMap, id)
	self.delSessionCount++
}

func (self *SessionManagerImplement) GetSessionChangeCount() (int, int) {
	return self.newSessionCount, self.delSessionCount
}

func (self *SessionManagerImplement) ResetSessionChangeCount() {
	self.newSessionCount = 0
	self.delSessionCount = 0
}

// 获得一个连接
func (self *SessionManagerImplement) GetSession(id int) *SocketSession {
	self.sesMapGuard.RLock()
	defer self.sesMapGuard.RUnlock()

	v, ok := self.sesMap[id]
	if ok {
		return v
	}

	return nil
}

func (self *SessionManagerImplement) SetSession(id int, ses *SocketSession) {
	self.sesMapGuard.Lock()
	defer self.sesMapGuard.Unlock()

	self.sesMap[id] = ses
}

func (self *SessionManagerImplement) VisitSession(callback func(*SocketSession) bool) {
	self.sesMapGuard.RLock()
	defer self.sesMapGuard.RUnlock()

	for _, ses := range self.sesMap {
		if !callback(ses) {
			break
		}
	}

}

func (self *SessionManagerImplement) CloseAllSession() {

	self.VisitSession(func(ses *SocketSession) bool {

		ses.Close(nil, nil)

		return true
	})
}

func (self *SessionManagerImplement) SessionCount() int {
	self.sesMapGuard.Lock()
	defer self.sesMapGuard.Unlock()

	return len(self.sesMap)
}

func NewSessionManager() SessionManager {
	return &SessionManagerImplement{
		sesMap: make(map[int]*SocketSession),
	}
}
